﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Web.UI;
using System.Web.UI.WebControls;
using Library;

namespace DirectoryWeb
{
  /// <summary>
  /// 組織単位リスト画面のフォームです。
  /// </summary>
  public partial class OUList : Page
  {
    #region プライベートフィールド
    //直下のオブジェクト格納用(OU自身のパス, 直下のオブジェクトの名前と種類と説明を格納したデータソース用のテーブル)
    private Dictionary<string, DataTable> domainObjectsInfos;
    private List<OrganizationalUnit> ouCol;   //OUのコレクション
    #endregion

    #region イベントハンドラ
    protected void Page_Load(object sender, EventArgs e)
    {
      if (base.Page.IsPostBack)   //ポストバックの時
      {
        domainObjectsInfos = (Dictionary<string, DataTable>)ViewState["domainObjectsInfos"];
        return;
      }

      var ous = DirectoryAccess.GetOrganizationalUnits();   //OUを取得
      ouCol = ous.OrderBy(ou => ou.DisplayPath).ThenBy(ou => ou.Name).ToList();
      this.CountLabel.Text = String.Format("{0} 個のオブジェクト", ous.Count);

      domainObjectsInfos = new Dictionary<string, DataTable>();
      ViewState["domainObjectsInfos"] = domainObjectsInfos;
      this.AddChildNode(null);  //子ノードを追加
    }

    protected void DetailDataSource_Selecting(object sender, ObjectDataSourceSelectingEventArgs e)
    {
      if (this.OUTreeView.SelectedNode == null)
      {
        e.Cancel = true;
      }
    }

    protected void DetailDataSource_Selected(object sender, ObjectDataSourceStatusEventArgs e)
    {
      this.DataPanel.Visible = true;
      this.ShowStoredData((OrganizationalUnit)e.ReturnValue);   //格納されているデータを表示
    }

    protected void Button1_Click(object sender, EventArgs e)
    {
      Response.Redirect("Main.aspx?idx=3");
    }
    #endregion

    #region プライベートメソッド
    /// <summary>
    /// 子ノードを追加します。
    /// </summary>
    /// <param name="node">子ノードを追加するノード。</param>
    private void AddChildNode(TreeNode node)
    {
      var path = (node == null) ? String.Empty : node.ValuePath;
      var childOUs = ouCol.Where(ou => ou.DisplayPath.Equals(path)).ToList();   //直下のOU

      foreach (var ou in childOUs)
      {
        var childNode = CreateNode(ou);   //ノードを作成
        if (node == null)
        {
          this.OUTreeView.Nodes.Add(childNode);
        }
        else
        {
          node.ChildNodes.Add(childNode);
        }
        this.AddChildNode(childNode);   //子ノードを追加
      }
    }

    /// <summary>
    /// 指定した OU のノードを作成します。
    /// </summary>
    /// <param name="ou">OU。</param>
    /// <returns>作成したノード。</returns>
    private TreeNode CreateNode(OrganizationalUnit ou)
    {
      var path = (ou.DisplayPath.Length == 0) ? String.Empty : ou.DisplayPath + "/";
      return new TreeNode(ou.Name, path + ou.Name);
    }

    /// <summary>
    /// 指定した OU に格納されているデータを表示します。
    /// </summary>
    /// <param name="ou">OU。</param>
    private void ShowStoredData(OrganizationalUnit ou)
    {
      DataTable table;
      if (domainObjectsInfos.TryGetValue(this.OUTreeView.SelectedValue, out table) == false)  //直下のオブジェクトを格納していない時
      {
        table = CreateDataSourceTable();  //データソース用のテーブルを作成
        foreach (var domainObject in ou.StoredDomainObjects)  //直下のオブジェクト数分
        {
          var row = table.NewRow();
          var objectType = (CategoryType)Enum.Parse(typeof(CategoryType), domainObject.Entry.SchemaClassName, true);
          row[0] = domainObject.Name;   //名前をセット
          row[1] = DirectoryAccess.CategoryNames[(int)objectType];  //種類をセット
          row[2] = domainObject.Description;  //説明をセット
          table.Rows.Add(row);
        }
        domainObjectsInfos.Add(this.OUTreeView.SelectedValue, table);
      }

      this.DataCountLabel.Text = String.Format("{0} 個のオブジェクト", table.Rows.Count);
      this.DataCountLabel.Visible = table.Rows.Count > 0;
      this.DataGridView.DataSource = table;
      this.DataGridView.DataBind();
    }

    /// <summary>
    /// データソース用のテーブルを作成します。
    /// </summary>
    /// <returns>データソース用のテーブル。</returns>
    private DataTable CreateDataSourceTable()
    {
      var table = new DataTable();
      table.Columns.Add(new DataColumn("Name", typeof(string)));
      table.Columns.Add(new DataColumn("Type", typeof(string)));
      table.Columns.Add(new DataColumn("Description", typeof(string)));
      return table;
    }
    #endregion
  }
}